package com.yaofeng.mybatis.modules.sys.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yaofeng.mybatis.common.ErrorCodeEnum;
import com.yaofeng.mybatis.exception.BusinessException;
import com.yaofeng.mybatis.modules.sys.entity.Dept;
import com.yaofeng.mybatis.modules.sys.entity.User;
import com.yaofeng.mybatis.modules.sys.mapper.DeptMapper;
import com.yaofeng.mybatis.modules.sys.mapper.UserMapper;
import com.yaofeng.mybatis.modules.sys.service.IDeptService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yaofeng.mybatis.modules.sys.vo.SelectTreeVo;
import com.yaofeng.mybatis.util.SelectTreeBuildUtil;
import com.yaofeng.mybatis.util.constants.UserConstants;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 部门表 服务实现类
 * </p>
 *
 * @author yaofeng
 * @since 2019-11-05
 */
@Service
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements IDeptService {

    @Resource
    private DeptMapper deptMapper;

    @Resource
    private UserMapper  userMapper;


    @Override
    public List<SelectTreeVo> buildSelectTreeNode(Map<String, Object> params) {
        List<SelectTreeVo> menuList = deptMapper.findAll(params);
        if (!CollectionUtils.isEmpty(menuList)) {
            SelectTreeBuildUtil treeBuildUtil = new SelectTreeBuildUtil(menuList);
            menuList = treeBuildUtil.builTree();
        }
        return menuList;
    }

    @Override
    public void saveDept(Dept dept) {
        // 1 判断部门名称是否唯一
        Dept entity = deptMapper.selectOne(Wrappers.<Dept>lambdaQuery().eq(StringUtils.isNotEmpty(dept.getDeptName()), Dept::getDeptName, dept.getDeptName()));
        if (entity != null) {
            throw new BusinessException(ErrorCodeEnum.DEPT_EXIST);
        }
        // 2 判断父节点是否启用  否则不允许添加
        entity = deptMapper.selectById(dept.getParentId());
        if (entity.getStatus() == 1) {
            throw new BusinessException(ErrorCodeEnum.DEPT_PARENT_STOP);
        }
        // 3 保存部门
        dept.setAncestors(entity.getAncestors() + "," + dept.getParentId());
        deptMapper.insert(dept);
    }

    @Transactional
    @Override
    public void updateDept(Dept dept) {

        /**
         *  1. 判断部门名称是否唯一
         */
        int count = deptMapper.checkUniqueDeptName(dept.getDeptId(),dept.getDeptName());
        if(count>0){
            throw new BusinessException(ErrorCodeEnum.DEPT_EXIST);
        }

        /**
         *  2. 判断上级部门不能是自己
         */
        if(dept.getDeptId().equals(dept.getParentId())){
            throw new BusinessException(ErrorCodeEnum.DEPT_NOT_SELF);
        }

        /**
         *  3. 判断上下级部门不能同时互相挂靠
         */
        Dept parentDeptInfo = deptMapper.selectById(dept.getParentId());
        if(parentDeptInfo.getParentId().equals(dept.getDeptId())){
            throw new BusinessException(ErrorCodeEnum.DEPT_SET_ERROR);
        }
        /**
         *  4. 更新操作
         */
        Dept  oldDeptInfo  = deptMapper.selectById(dept.getDeptId());
        String newAncestors = parentDeptInfo.getAncestors() + "," + parentDeptInfo.getDeptId();
        String oldAncestors = oldDeptInfo.getAncestors();
        dept.setAncestors(newAncestors);
        deptMapper.updateById(dept);
        // 查询旧的部门节点需要更新 ancestors的节点集合
        List<Dept>  updateDepts =  deptMapper.selectList(Wrappers.<Dept>lambdaQuery().like(Dept::getAncestors,dept.getDeptId()));
        updateDepts.forEach(o ->{
            o.setAncestors(o.getAncestors().replace(oldAncestors, newAncestors));
            deptMapper.updateById(o);
        } );

        // 如果该部门是启用状态，则启用该部门的所有上级部门
        if(UserConstants.DEPT_STATUS_YES.equals(dept.getStatus())){
            deptMapper.updatePatrentDeptStatus(newAncestors);
        }

    }

    @Override
    public void deleteDept(Long id) {
        Integer  deptCount   = deptMapper.selectCount(Wrappers.<Dept>lambdaQuery().eq(Dept::getParentId,id));
        if(deptCount>0){
            throw new BusinessException(ErrorCodeEnum.DEPT_CHILD_EXIST);
        }
        Integer   userCount   = userMapper.selectCount(Wrappers.<User>lambdaQuery().eq(User::getDeptId,id));
        if(userCount>0){
            throw new BusinessException(ErrorCodeEnum.DEPT_USER_EXIST);
        }
        deptMapper.deleteById(id);
    }
}
